package com.winit.deploy.task.tomcatTask;

import com.winit.common.util.ConfigUtil;
import com.winit.common.util.JSONFileUtil;
import com.winit.core.server.base.CmdOutputHandler;
import com.winit.core.task.Task;
import com.winit.deploy.bean.DeployTaskStatus;
import com.winit.deploy.bean.WinitTomcatInfo;
import com.winit.deploy.server.WinitTomcatServer;
import com.winit.deploy.util.DeployFileUtil;
import com.winit.deploy.util.DeployMessageUtil;
import com.winit.deploy.util.DeployUtil;
import com.winit.project.util.ProjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * Created by wangjian on 16/8/10.
 * 发布任务step2 停server
 */
public class DeployStopServerTask extends Task {

    static final Logger logger = LoggerFactory.getLogger(DeployStopServerTask.class);

    private WinitTomcatServer winitTomcatServer;

    public DeployStopServerTask(String taskId, Integer expireTime, WinitTomcatServer winitTomcatServer) {
        super(taskId, expireTime);
        this.winitTomcatServer = winitTomcatServer;
    }

    @Override
    public TaskStatus call() throws Exception {
        logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.call start taskId=" + this.taskId);
        String config = ConfigUtil.getValue("tomcat_use_shutdown");
        logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.call config=" + config);
        //虚拟机环境 直接kill
        if (StringUtils.isEmpty(config)
                || !"true".equals(config)
                || this.winitTomcatServer.getWinitTomcatInfo().isVmEnv()) {
            logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.call 虚拟机环境直接kill");
            this.killServer();
            logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.call end taskId=" + this.taskId);
            return TaskStatus.STATUS_SUCCESS;
        }

        if (!this.isContinue) {
            //tomcat 未启动 直接返回
            if (this.shutdownServer().startsWith("tomcat service is not running!")) {
                this.sendMessage("tomcat未启动");
                logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.call end taskId=" + this.taskId);
                return TaskStatus.STATUS_SUCCESS;
            }
            Thread.sleep(this.getSleepTime());
            if (this.serverStatus().startsWith("tomcat service is not running")) {
                this.sendMessage("tomcat已经通过shutdown关闭");
                logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.call end taskId=" + this.taskId);
                return TaskStatus.STATUS_SUCCESS;
            }
        }
        this.killServer();
        DeployUtil.saveProjectWithKill(this.winitTomcatServer.getWinitTomcatInfo().getProjectName());
        this.sendMessage("tomcat已经通过kill关闭");
        logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.call end taskId=" + this.taskId);
        return TaskStatus.STATUS_SUCCESS;
    }

    private String shutdownServer() throws Exception {
        final StringBuffer str = new StringBuffer();
        CmdOutputHandler handler = new CmdOutputHandler() {
            @Override
            public void onMessage(String cmd, int index, String message, Boolean isErrorMessage) {
                str.append(message);
            }
        };
        this.winitTomcatServer.doStopServer(handler);
        logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.shutdownServer str=" + str.toString());
        if ((str.toString()).startsWith("Shutdown Tomcat complete ok") ||
                (str.toString()).startsWith("tomcat service is not running!")) {
            return str.toString();
        } else {
            throw new Exception(str.toString());
        }
    }

    private String serverStatus() throws Exception {
        final StringBuffer str = new StringBuffer();
        CmdOutputHandler handler = new CmdOutputHandler() {
            @Override
            public void onMessage(String cmd, int index, String message, Boolean isErrorMessage) {
                str.append(message);
            }
        };
        this.winitTomcatServer.serverStatus(handler);
        logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.serverStatus str=" + str.toString());
        if ((str.toString()).startsWith("tomcat service is running") ||
                (str.toString()).startsWith("tomcat service is not running")) {
            return str.toString();
        } else {
            throw new Exception(str.toString());
        }
    }

    private void killServer() throws Exception {
        final StringBuffer str = new StringBuffer();
        CmdOutputHandler handler = new CmdOutputHandler() {
            @Override
            public void onMessage(String cmd, int index, String message, Boolean isErrorMessage) {
                str.append(message);
            }
        };
        this.winitTomcatServer.killServer(handler);
        logger.info("com.winit.deploy.task.tomcatTask.DeployStopServerTask.killServer str=" + str.toString());
        if (!(str.toString()).startsWith("Kill Tomcat complete ok") &&
                !(str.toString()).startsWith("tomcat service is not running!")) {
            throw new Exception(str.toString());
        }
    }

    private void sendMessage(String msg) {
        WinitTomcatInfo info = this.winitTomcatServer.getWinitTomcatInfo();
        String envName = info.getEnvName();
        String areaName = info.getAreaName();
        DeployMessageUtil.tomcatStopType(info.getQueueName(), envName, areaName, this.taskId, msg);

        DeployFileUtil.handelAreaTaskStatus(envName, areaName, taskId, null, info.getProjectName(), info.getEditionNum(), msg,null);
    }

    /**
     * tomcat shutdown等待时间
     *
     * @return
     */
    private Integer getSleepTime() {
        Integer time = 10000;
        String trunkName = ProjectUtil.getTrunkProjectName(this.winitTomcatServer.getWinitTomcatInfo().getProjectName());
        Map<String, Integer> timeMap = JSONFileUtil.getFileJsonForBean(Thread.currentThread().getContextClassLoader().getResource("").getPath()
                + "data/sleep_time.json", Map.class);
        if (timeMap.containsKey(trunkName)) {
            time = timeMap.get(trunkName);
        }
        return time;
    }
}
